#include "../../../include/online/Dictionary.hpp"
#include "../../../include/online/Configuration.hpp"

/*
 * 警告：将字符串转为数字不要用C++定义在头文件string里的stoi
 * 会发生运行时错误，现在将string类型转为c风格字符串
 * 再用atoi将c风格字符串转为数字
 * */

/* 
 * 当前文件测试通过，依赖文件如下（注意路径）
 *
 * 配置文件存放路径 searchEngine/conf/myconf.conf
 * 当前文件路径：searchEngine/src/online/part1/Dictionary.cpp
 * 测试文件路径：searchEngine/src/online/part1/testDictionary.cpp
 * 依赖文件1：searchEngine/include/Configuration.h
 * 依赖文件2：searchEngine/src/online/part1/Configuration.cpp
 * */

#include <iostream>
#include <sstream>
#include <fstream>

using std::cout;
using std::endl;
using std::ifstream;
using std::istringstream;

Dictionary *Dictionary::_pInstance = getInstance(); //饿汉模式
Dictionary *Dictionary::getInstance() {
    if (_pInstance == nullptr) {
        _pInstance = new Dictionary();
        _pInstance->initDict();
        _pInstance->initIndex();
        atexit(destroy);
    }
    return _pInstance;
}

void Dictionary::destroy() {
    if (_pInstance) {
        delete _pInstance;
        _pInstance = nullptr;
    }
}

void Dictionary::initDict() {
    string dictPath = Configuration::getInstance()->getConfigMap()["enDict"];

    ifstream ifs(dictPath);
    if (!ifs) {
        cout << "Dictionary::initDict(): enDict ifs is not good" << endl;
        return;
    }
    string line;
    while (getline(ifs, line)) {
        istringstream iss(line);
        string word, freq;
        iss >> word >> freq;
        if(word != ""){
            _dict[word] = atoi(freq.c_str());
        }
    }
    
    /* for(auto &elem : _dict){ */
    /*     cout << elem.first << " " << elem.second << endl; */
    /* } */

    //读取中文字典
    dictPath = Configuration::getInstance()->getConfigMap()["cnDict"];
    ifstream ifs2(dictPath);
    if(!ifs2) {
        cout << "Dictionary::initDict: cnDict ifs is not good" << endl;
    }
    while(getline(ifs2, line)){
        istringstream iss(line);
        string word, freq;
        iss >> word >> freq;
        if(word != ""){
            _dict[word] = atoi(freq.c_str());
        }
    }

    /* for(auto &elem : _dict){ */
    /*     cout << elem.first << " " << elem.second << endl; */
    /* } */
    cout << "initDict finished" << endl;
    cout << "_dict.size() = " << _dict.size() << endl;
}

//测试正常通过
void Dictionary::initIndex() {
    //读取英文索引
    string dictIndexPath = Configuration::getInstance()->getConfigMap()["enDictIndex"];
    ifstream ifs(dictIndexPath);
    if (!ifs.good()) {
        cout << "Dictionary::initIndex: enDictIndex ifs is not good" << endl;
        return;
    }
    string line;
    while (getline(ifs, line)) {
        istringstream iss(line);
        string word, lineNo;
        iss >> word;
        while (iss >> lineNo) {
            _index[word].insert(atoi(lineNo.c_str()));
        }
        /* cout << word << " set.size() = " << _index[word].size() << endl; */
    }
    dictIndexPath = Configuration::getInstance()->getConfigMap()["cnDictIndex"];
    ifstream ifs2(dictIndexPath);
    if (!ifs2.good()) {
        cout << "Dictionary::initIndex: enDictIndex ifs is not good" << endl;
        return;
    }
    while (getline(ifs2, line)) {
        istringstream iss(line);
        string word, lineNo;
        iss >> word;
        while (iss >> lineNo) {
            _index[word].insert(atoi(lineNo.c_str()));
        }
        /* cout << word << " set.size() = " << _index[word].size() << endl; */
    }
}

const unordered_map<string, int> &Dictionary::getDict() {
    return _dict;
}

const unordered_map<string, set<int>> &Dictionary::getIndexTable() {
    return _index;
}

